package cn.com.lms.business.exam.web;

import cn.com.lms.business.core.constant.ErrorEnum;
import cn.com.lms.business.core.util.SystemUserUtil;
import cn.com.lms.business.exam.enums.SubjectTypeEnum;
import cn.com.lms.business.exam.service.PaperSubjectService;
import cn.com.lms.business.exam.service.QuestionService;
import cn.com.lms.business.exam.web.vo.QuestionIdVO;
import cn.com.lms.business.exam.web.vo.QuestionSubjectExportVO;
import cn.com.lms.business.exam.web.vo.QuestionSubjectVO;
import cn.com.lms.business.excel.ExcelSheetDataDTO;
import cn.com.lms.business.exam.persistence.entity.*;
import cn.com.lms.business.exam.service.QuestionSubjectService;
import cn.com.lms.business.user.persistence.entity.SysUserVo;
import com.alibaba.fastjson.JSON;

import com.bnzj.core.exception.BusinessException;
import com.bnzj.core.export.Column;
import com.bnzj.core.persistence.query.CompareExpression;
import com.bnzj.core.persistence.query.CompareType;
import com.bnzj.core.persistence.query.IExpression;

import com.bnzj.core.persistence.query.QueryHelpBean;
import com.bnzj.core.rest.ResponseResult;


import com.bnzj.core.util.BeanUtils;
import com.bnzj.core.webmvc.util.WebMvcUtils;

import com.fasterxml.jackson.databind.util.BeanUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.hibernate.internal.util.StringHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * @author zhangzhenjiang
 * @createDate 2020/3/14
 * @description
 */
@Tag(name = "试题", description = "试题管理")
@RestController
@RequestMapping("/exam/question/subject")
public class QuestionSubjectController {

    @Autowired
    QuestionSubjectService questionSubjectService;

    @Autowired
    QuestionService questionService;

    @Autowired
    PaperSubjectService paperSubjectService;



    @Operation(summary = "分页查询", description = "",
            parameters = {
                    @Parameter(name = "keyWord", description = "关键子查询，题目名称进行模糊查询", allowEmptyValue = true,
                            allowReserved = true, schema = @Schema(implementation = String.class, description = "keyWord")),
                    @Parameter(name = "type", description = "题型 1-单选题 2-多选题 3判断题 4填空题 5问答题", allowEmptyValue = true,
                            allowReserved = true, schema = @Schema(implementation = Short.class, description = "type")),
                    @Parameter(name = "questionId", description = "题库ID", allowEmptyValue = true,
                            allowReserved = true, schema = @Schema(implementation = Long.class, description = "questionId")),
                    @Parameter(name = "limit", description = "分页大小", allowEmptyValue = true, allowReserved = true, schema = @Schema(type = "int", description = "分页大小")),
                    @Parameter(name = "offset", description = "页码", allowEmptyValue = true, allowReserved = true, schema = @Schema(type = "int", description = "页码")),
            })
    @GetMapping(value = "/page")
    public ResponseResult<Page<QuestionSubjectVO>> getQuestionSubjectPage(HttpServletRequest request) {
        Long questionId = StringHelper.isNotEmpty(request.getParameter("questionId")) ? Long.parseLong(request.getParameter("questionId")) : null;
        Short type = StringHelper.isNotEmpty(request.getParameter("type")) ? Short.parseShort(request.getParameter("type")) : null;
        String keyWord = request.getParameter("keyWord");


        Pageable pageable = WebMvcUtils.initPage(request, Sort.by(Sort.Direction.DESC, "qs.create_time"));
        QueryHelpBean queryHelpBean = QuestionSubjectService.getQueryHelpBean();
        queryHelpBean.setPageable(pageable);

        //根据题目名称，模糊搜索
        if (StringHelper.isNotEmpty(keyWord)) {
            IExpression orCondition1 = CompareExpression.build("qs.subject", CompareType.like, keyWord);
            queryHelpBean.addWhere(orCondition1);
        }
        if (type != null) {
            IExpression andCondition2 = CompareExpression.build("qs.type", CompareType.equal, type);
            queryHelpBean.addWhere(andCondition2);
        }
        if (questionId != null) {
            IExpression andCondition3 = CompareExpression.build("qs.question_id", CompareType.equal, questionId);
            queryHelpBean.addWhere(andCondition3);
        }

        IExpression andCondition4 = CompareExpression.build("qs.is_delete", CompareType.equal, false);
        queryHelpBean.addWhere(andCondition4);


        Page<QuestionSubjectVO> all = questionSubjectService.findAll(queryHelpBean);
        all.stream().forEach(questionSubjectVO -> {
            if (SubjectTypeEnum.JUDGE.getValue().equals(questionSubjectVO.getType())) {
                //根据试题ID,查询判断题答案
                questionSubjectVO.setOptions("A 正确###B 错误");
                if (questionSubjectVO.getAnswer().equals("false") || questionSubjectVO.getAnswer().equals("正确")) {
                    questionSubjectVO.setAnswer("A");
                }
                if (questionSubjectVO.getAnswer().equals("true") || questionSubjectVO.getAnswer().equals("错误")) {
                    questionSubjectVO.setAnswer("B");
                }
            }

        });
        return ResponseResult.success( );
    }

    @Operation(summary = "根据id查询")
    @GetMapping("/one/{id}")
    public ResponseResult<QuestionSubject> getById(@Parameter(in = ParameterIn.PATH, name = "id", description = "主键", required = true) @PathVariable("id") Long id) {
        Optional<QuestionSubject> questionSubjectOpt = questionSubjectService.findById(id);
        if (!questionSubjectOpt.isPresent()) {
            throw new BusinessException(ErrorEnum.RECORD_NOT_EXIST.getMessage(), "" + ErrorEnum.RECORD_NOT_EXIST.getCode());
        }
        return ResponseResult.success(questionSubjectOpt.get());
    }

    @Operation(summary = "保存")
    @PostMapping("/save")
    public ResponseResult<?> addQuestionSubject(@RequestBody QuestionSubject questionSubject) {
        SysUserVo sysUser = SystemUserUtil.getCurrentUser();

        questionSubject.setModifyTime(new Date());
        questionSubject.setCreator(String.valueOf(sysUser.getId()) );
        questionSubject.setCreateTime(new Date());
        questionSubject.setCreatorName( sysUser.getCname());

        questionSubjectService.addQuestionSubject(questionSubject);
        return ResponseResult.success();
    }


    @Operation(summary = "更新")
    @PostMapping("/update")
    public ResponseResult<?> updateQuestionSubject(@RequestBody QuestionSubject questionSubject) {
        if (ObjectUtils.isEmpty(questionSubject.getId())) {
            throw new BusinessException(ErrorEnum.PARAMETER_CANNOT_BE_EMPTY.getMessage(), "" + ErrorEnum.PARAMETER_CANNOT_BE_EMPTY.getCode());
        }


        SysUserVo sysUser = SystemUserUtil.getCurrentUser();
        questionSubject.setModifyTime(new Date());
        questionSubject.setCreator(String.valueOf(sysUser.getId()));
        questionSubject.setCreateTime(new Date());
        questionSubject.setCreatorName(sysUser.getCname());
        questionSubjectService.updateQuestionSubject(questionSubject);
        return ResponseResult.success();
    }


    @Operation(summary = "根据id复制")
    @GetMapping("/copy/{id}")
    public ResponseResult<QuestionSubject> copyById(@Parameter(in = ParameterIn.PATH, name = "id", description = "主键", required = true) @PathVariable("id") Long id) {
        Optional<QuestionSubject> questionSubjectOpt = questionSubjectService.findById(id);
        if (!questionSubjectOpt.isPresent()) {
            throw new BusinessException(ErrorEnum.RECORD_NOT_EXIST.getMessage(), "" + ErrorEnum.RECORD_NOT_EXIST.getCode());
        }
        QuestionSubject source = questionSubjectOpt.get();
        QuestionSubject questionSubject = new QuestionSubject();
        BeanUtils.copyProperties(source, questionSubject);
        questionSubject.setSubject("(复制)" + questionSubject.getSubject());
        questionSubject.setId(0L);
        QuestionSubject result = questionSubjectService.addQuestionSubject(questionSubject);
        return ResponseResult.success(questionSubject);
    }


    @Operation(summary = "删除，批量删除", description = "根据分类id删除试题")
    @PostMapping("/delete")
    public ResponseResult<Integer> deleteById(@RequestBody List<Long> id) {


        List<Map> paperMapList = paperSubjectService.findBySubjectIdList(id);
        if (paperMapList.size() > 0) {
            throw new BusinessException(ErrorEnum.PAPER_SUIBJECT_EXIST.getMessage(), "" + ErrorEnum.PAPER_SUIBJECT_EXIST.getCode());
        }
        Integer count = questionSubjectService.updateIsDelete(true, id);
        return ResponseResult.success(count);

    }


    @Operation(summary = "移动,批量移动", description = "根据分类id移动试题", parameters = {
            @Parameter(name = "questionId", description = "题库ID", allowEmptyValue = false,
                    allowReserved = true, schema = @Schema(implementation = Long.class, description = "questionId")),
    })
    @PostMapping("/move")
    public ResponseResult<Integer> moveById(@RequestParam(name = "questionId") Long questionId, @RequestBody List<Long> id) {
        Integer count = questionSubjectService.updateQuestionId(questionId, id);
        return ResponseResult.success(count);

    }

    @Operation(summary = "导入", description = "根据模板导入试题", parameters = {
            @Parameter(name = "questionId", description = "题库ID", allowEmptyValue = false,
                    allowReserved = true, schema = @Schema(implementation = Long.class, description = "questionId")),
    })
    @RequestMapping(value = "/import", method = RequestMethod.POST)
    public ResponseResult<?> importExcel(MultipartFile file, Long questionId) {

        Optional<Question> question = questionService.findById(questionId);
        if (!question.isPresent()) {
            throw new BusinessException(ErrorEnum.RECORD_NOT_EXIST.getMessage(), "" + ErrorEnum.RECORD_NOT_EXIST.getCode());
        }

        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<ExcelSheetDataDTO> excelSheetDataDTOList = questionSubjectService.importExcelByInutStream(inputStream, questionId);


        return ResponseResult.success(excelSheetDataDTOList);
    }


    @Operation(summary = "导出", description = "根据模板导出试题", parameters = {
            @Parameter(name = "questionId", description = "题库ID", allowEmptyValue = false,
                    allowReserved = true, schema = @Schema(implementation = Long.class, description = "questionId")),
    })
    @RequestMapping(value = "/export", method = RequestMethod.POST)
    public void exportExcel(@RequestBody QuestionIdVO questionIdVO, HttpServletResponse response) {
        Map map=new HashMap();
        Long questionId = questionIdVO.getQuestionId();
        List<Long> questionIdList = Arrays.asList(questionId);
        List<Long> selectedRowKeys = questionIdVO.getSelectedRowKeys();
        List<QuestionSubjectExportVO> questionSubjectExportVOList = questionSubjectService.findQuestionSubjectExportVOByQuestionIdList(questionIdList);
        map.put("beforeList",questionSubjectExportVOList);
        List<QuestionSubjectExportVO> afterFilterList=new CopyOnWriteArrayList<>();
        if(!CollectionUtils.isEmpty(questionIdVO.getSelectedRowKeys())){
            afterFilterList=questionSubjectExportVOList.stream().filter(m->selectedRowKeys.contains(m.getSubjectId())).collect(Collectors.toList());
            map.put("afterList",afterFilterList);
        }else{
            afterFilterList=questionSubjectExportVOList;
        }

        HSSFWorkbook hssfWorkbook = questionSubjectService.exportQuestionSubject(afterFilterList);
        response.setContentType("application/octet-stream");

        //默认Excel名称
        response.setHeader("Content-Disposition", "attachment;fileName=" + "exam" + questionId + ".xls");

        try {
            response.flushBuffer();
            hssfWorkbook.write(response.getOutputStream());
        } catch (IOException e) {
//            e.printStackTrace();
        }

    }


    @Operation(summary = "下载模板", description = "下载试题模板")
    @RequestMapping(value = "/downloadTemplate", method = RequestMethod.POST)
    public void downloadTemplate(HttpServletResponse response) {

        List<QuestionSubjectExportVO> questionSubjectExportVOList = new ArrayList<>();
        HSSFWorkbook hssfWorkbook = questionSubjectService.exportQuestionSubject(questionSubjectExportVOList);
        response.setContentType("application/octet-stream");
        //默认Excel名称
        response.setHeader("Content-Disposition", "attachment;fileName=template.xls");


        try {
            response.flushBuffer();
            hssfWorkbook.write(response.getOutputStream());
        } catch (IOException e) {
//            e.printStackTrace();
        }

    }

    @Operation(summary = "文件访问", description = "文件访问")
    @RequestMapping(value = "/accessFile", method = RequestMethod.POST)
    public void accessFile(HttpServletResponse response, HttpServletRequest request) throws IOException {

        String filePath = "http://zzj0222.natapp1.cc/playlist.m3u8";
        URL url = new URL(filePath);
        InputStream fis = null;
        String agent = request.getHeader("User-Agent").toUpperCase();
        response.setHeader("Access-Control-Allow-Origin","*");
        OutputStream os = null;

        // 得到数据
        byte[] imageFromURL = getImageFromURL(filePath);

        try {
            fis = url.openStream();
            fis.read(imageFromURL);
            response.reset();
            if(agent.indexOf("FIREFOX") != -1){//火狐浏览器

               response.addHeader("Content-Disposition", "attachment;filename="+ new String("test.m3u8".getBytes("GB2312"),"ISO-8859-1"));

            }else{//其他浏览器
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("test.m3u8", "UTF-8"));

            }

//            response.setHeader("Content-type", "video/mpeg4;charset=UTF-8");
            response.setContentType("application/octet-stream");
//            response.setHeader("Content-Length", Integer.toString(imageFromURL.length));
            os = response.getOutputStream();
            os.write(imageFromURL);

        } catch (Exception e) {

        } finally {

            if(os!=null) {
                os.flush();
                os.close();
            }
        }


    }

    /**
     * 根据图片地址获取图片信息
     *
     * @param urlPath 网络图片地址
     * @return
     */
    public static byte[] getImageFromURL(String urlPath) {
        // 字节数组
        byte[] data = null;
        // 输入流
        InputStream is = null;
        // Http连接对象
        HttpURLConnection conn = null;
        try {
            // Url对象
            URL url = new URL(urlPath);
            // 打开连接
            conn = (HttpURLConnection) url.openConnection();
            // 打开读取 写入是setDoOutput
//	        conn.setDoOutput(true);
            conn.setDoInput(true);
            // 设置请求方式
            conn.setRequestMethod("GET");
            // 设置超时时间
            conn.setConnectTimeout(6000);
            // 得到访问的数据流
            is = conn.getInputStream();
            // 验证访问状态是否是200 正常
            if (conn.getResponseCode() == 200) {
                data = readInputStream(is);
            } else {
                data = null;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    // 关闭流
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 关闭连接
            conn.disconnect();
        }
        return data;
    }

    /**
     * 将流转换为字节
     *
     * @param is
     * @return
     */
    public static byte[] readInputStream(InputStream is) {
        /**
         * 捕获内存缓冲区的数据，转换成字节数组
         * ByteArrayOutputStream类是在创建它的实例时，程序内部创建一个byte型别数组的缓冲区，然后利用ByteArrayOutputStream和ByteArrayInputStream的实例向数组中写入或读出byte型数据。
         * 在网络传输中我们往往要传输很多变量，我们可以利用ByteArrayOutputStream把所有的变量收集到一起，然后一次性把数据发送出去。
         */
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // 创建字节数组 1024 = 1M
        byte[] buffer = new byte[1024];
        // 防止无限循环
        int length = -1;
        try {
            // 循环写入数据到字节数组
            while ((length = is.read(buffer)) != -1) {
                baos.write(buffer, 0, length);
            }
            // 强制刷新，扫尾工作，主要是为了，让数据流在管道的传输工程中全部传输过去，防止丢失数据
            baos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 字节流转换字节数组
        byte[] data = baos.toByteArray();
        try {
            // 关闭读取流
            is.close();
            // 关闭写入流
            baos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }

    /**
     * 获取本地图片的字节数
     *
     * @param imgPath
     * @return
     */
    public static String pathSize(String imgPath) {
        File file = new File(imgPath);
        FileInputStream fis;
        int fileLen = 0;
        try {
            fis = new FileInputStream(file);
            fileLen = fis.available();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bytes2kb(fileLen);
    }

    /**
     * 将获取到的字节数转换为KB，MB模式
     *
     * @param bytes
     * @return
     */
    public static String bytes2kb(long bytes) {
        BigDecimal filesize = new BigDecimal(bytes);
        BigDecimal megabyte = new BigDecimal(1024 * 1024);
        float returnValue = filesize.divide(megabyte, 2, BigDecimal.ROUND_UP).floatValue();
        if (returnValue > 1)
            return (returnValue + "MB");
        BigDecimal kilobyte = new BigDecimal(1024);
        returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP).floatValue();
        return (returnValue + "KB");
    }


    public static void main(String[] args) {
//        List<String> answerList= Arrays.asList("李白","杜甫");
        List<String> answerList = null;
        String strJson = JSON.toJSONString(answerList);
        System.out.println(strJson);
        List<String> list = JSON.parseArray(strJson, String.class);
        System.out.println(list);
        System.out.println(answerList);

    }


}
